using System.Reflection;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using Vin.Extension.Framework.Attributes;
using Vin.Extension.Framework.Options.Dto;
using Vin.Tool.AspNetCore.Singleton;

namespace Vin.Extension.Framework.Dto;

public record VinPrimaryEntityDto : IJsonOnSerializing, IJsonOnSerialized, IJsonOnDeserializing,
    IJsonOnDeserialized
{
    /// <summary>
    /// 业务主键
    /// </summary>
    public long? Id { get; set; }

    public static implicit operator bool(VinPrimaryEntityDto? exists)
    {
        return exists != null;
    }

    private bool _isSerialized = false;

    public virtual void OnSerializing()
    {
        if (_isSerialized)
            return;
        _isSerialized = true;
        var option = VinApp.GetConfig<DtoSerializerOption>();
        if (option.RouteIgnoreProperties.Count > 0 && VinApp.HaveHttpContext)
        {
            if (!option.RouteIgnoreProperties.Any(x => x.Rules.Any(r =>
                    Regex.IsMatch(VinApp.HttpContext.Request.Path.ToString().ToLower(), r.ToLower()))))
                return;

            var ignoreProperties = option.RouteIgnoreProperties.SelectMany(m => m.Properties).ToList();
            // 获取当前类是否包含 IgnoreSerializerRule 特性
            var ignoreSerializerRule = this.GetType().GetCustomAttribute<IgnoreSerializerRuleAttribute>();
            var notIgnorePropertyList = ignoreSerializerRule?.Properties ?? new HashSet<string>();
            var properties = this.GetType().GetProperties();
            foreach (var property in properties)
            {
                if (property.GetCustomAttribute<IgnoreSerializerRuleAttribute>() != null) continue;
                if (notIgnorePropertyList.Contains(property.Name)) continue;

                var propertyValue = property.GetValue(this);
                if (propertyValue == null)
                {
                    continue;
                }

                if (ignoreProperties.Any(x => x == property.Name))
                {
                    property.SetValue(this, null);
                }
            }
        }
    }

    public virtual void OnSerialized()
    {
    }

    public virtual void OnDeserializing()
    {
    }

    public virtual void OnDeserialized()
    {
    }
}